package objects;

import java.util.ArrayList;

import executors.Sort;


/**
 * This is ordered list to store Event. Required Event to implement compareTo
 * method. The oder of events in the list is based on the compareTo method
 * inside the Event.
 * 
 * @author JJP
 * @version 0.1
 */
public class SortedEventList {
	private ArrayList<Event> sortedEventList;

	public SortedEventList() {
		sortedEventList = new ArrayList<Event>();
	}

	@SuppressWarnings("unchecked")
	public ArrayList<Event> getArrayList() {
		return (ArrayList<Event>) sortedEventList.clone();
	}

	public SortedEventList(ArrayList<Event> eventList) {
		sortedEventList = Sort.sortByEndDate(eventList);
	}

	public boolean clear() {
		sortedEventList.clear();
		return true;
	}

	public boolean hasEvent(Event e) {
		return sortedEventList.contains(e);
	}

	public boolean isEmpty() {
		return sortedEventList.isEmpty();
	}

	public int size() {
		return sortedEventList.size();
	}

	public Event get(int index) {
		if (index < 0 || index >= sortedEventList.size()) {
			throw new IndexOutOfBoundsException("index<0 or >="
					+ sortedEventList.size());
		}
		return sortedEventList.get(index);
	}

	public boolean add(Event e) {
		if (sortedEventList.size() == 0) {
			sortedEventList.add(e);
		}
		int position = binarySearch(e);
		if (position >= 0) {
			return false;
		} else {
			sortedEventList.add(-position - 1, e);
			return true;
		}
	}

	public boolean remove(Event e) {
		if (sortedEventList.size() == 0) {
			return false;
		}
		int pos = binarySearch(e);
		if (pos < 0) {
			return false;
		}
		sortedEventList.remove(pos);
		return true;
	}

	public boolean remove(int pos) {
		if (pos < 0 || pos > sortedEventList.size()) {
			return false;
		}
		sortedEventList.remove(pos);
		return true;
	}

	public boolean set(int pos, Event e) {
		if (pos < 0 || pos > sortedEventList.size()) {
			return false;
		} else if (!(pos == binarySearch(e)))// ensure no interruption of the
												// order
		{
			return false;
		}
		sortedEventList.set(pos, e);
		return true;
	}

	private int binarySearch(Event e) {
		if (sortedEventList.size() == 0) {
			return -1;
		}
		int lo = 0, hi = sortedEventList.size() - 1;
		int mid = 0;
		while (lo <= hi) {
			mid = (lo + hi) / 2;
			int compareResult = e.compareTo(sortedEventList.get(mid));
			if (compareResult == 0) {
				return mid;
			} else if (compareResult < 0) {
				hi = mid - 1;
			} else {
				lo = mid + 1;
			}
		}
		if (e.compareTo(sortedEventList.get(mid)) < 0) {
			return (-(mid + 1));
		} else {
			return (-(mid + 2));
		}
	}

}
